import SSHConfig from 'ssh2-promise/lib/sshConfig'
import { SSHResultType } from '../types'
import { SSHUtil } from '../utils'
import { SSHTimeoutMiddleware } from './ssh-timeout'

export const SSHErrorMiddleware_Name = 'SSHErrorMiddleware'
export const SSHErrorMiddlewareType_Name = 'SSHErrorMiddlewareType'

/**
 * SSH 错误处理中间件
 *
 * @param fun 处理函数
 * @param options 配置选项
 * - config SSH 连接配置（host/port/username/password 等）
 * - timeout 超时时间，单位为 ms，默认 undefined，表示不额外设置超时时间限制
 * - thisArg 指定处理函数的 this 指向，默认为 null，即非严格模式下函数调用时的 this 指向全
 * 局对象，严格模式下为 thisArg 指定的值；对于需要节流处理的函数为箭头函数时，该参数无效，箭头
 * 函数的 this 指向由函数定义时确定，不受 thisArg 参数影响，箭头函数的 this 来源于箭头函数定
 * 义时的上级作用域。
 * @returns 返回值 增加了错误处理后的处理函数
 */
export const SSHErrorMiddleware = (
  fun: (...args: any[]) => Promise<SSHResultType>,
  options: {
    config?: SSHConfig
    timeout?: number
    thisArg?: any
  } = {}
): ((...args: any[]) => Promise<SSHResultType>) => {
  const { config, timeout, thisArg } = {
    config: {},
    timeout: undefined,
    thisArg: null,
    ...options
  }
  return async (...args: any[]): Promise<SSHResultType> => {
    try {
      if (timeout === undefined) return await fun.apply(thisArg, args)
      else {
        const closure = SSHTimeoutMiddleware(fun, { timeout, thisArg })
        return await closure(...args)
      }
    } catch (error) {
      return SSHUtil.errorHandler(error, config)
    }
  }
}

export type SSHErrorMiddlewareType = typeof SSHErrorMiddleware
